---
patternId: web-apps/badges
---

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="color-scheme" content="dark light" />
    <link rel="manifest" href="assets/manifest.json" />
    <title>How to create an app badge</title>
    <style>
      html {
        box-sizing: border-box;
        font-family: system-ui, sans-serif;
        color-scheme: dark light;
      }
      *, *:before, *:after {
        box-sizing: inherit;
      }
      body {
        margin: 1rem;
      }
      img {
        height: auto;
        max-width: 100%;
        display: block;
      }
    </style>
  </head>
  <body>
    <h1>How to create an app badge</h1>
    <style>
      own-window {
        border: dashed red 2px;
        padding: 0.25rem;
      }
    </style>
    <own-window>
      <div>This demo needs to run in its own window, not in an iframe.</div>
      <button type="button">Open in new window</button>
    </own-window>
    <ol>
      <li>
        Watch the favicon. You should see a counter that updates each second
        integrated into the favicon.
        <img
          src="assets/favicon.png"
          style="width: 250px; height: auto"
          width="528"
          height="74"
          alt="Favicon with counter."
        />
      </li>
      <li>
        Install the app by clicking the button below. After the installation,
        the button is disabled.
        <p>
          <button id="install" disabled type="button">Install</button>
        </p>
      </li>
      <li>
        Watch the app icon in your operating system's task bar. You should see a
        counter that updates each second as an app badge.
        <img
          src="assets/app-icon.png"
          style="width: 80px; height: auto"
          width="282"
          height="388"
          alt="App badge with counter."
        />
      </li>
    </ol>
    <favicon-badge src="data:image/svg+xml, %3Csvg enable-background='new 0 0 128 128' viewBox='0 0 128 128' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3ClinearGradient id='f' x1='83.081' x2='105.28' y1='36.552' y2='36.552' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%238D6E63' offset='.0037206'/%3E%3Cstop stop-color='%2376594F' offset='.4152'/%3E%3Cstop stop-color='%234E342E' offset='.9989'/%3E%3C/linearGradient%3E%3Cpath d='m89.2 43.21c-0.84-0.18-3.53-2.77-6.12-5.84 4.16-2.1 16.11-7.47 20.68-7.47 0.46 0 0.69 0.06 0.78 0.09 0.34 0.12 0.71 0.33 0.73 1.26 0.07 2.9-3.13 7.42-4.52 7.99l-1.24 0.52c-2.69 1.12-8.28 3.47-10.2 3.47-0.03-0.02-0.07-0.02-0.11-0.02z' fill='url(%23f)'/%3E%3Cpath d='m103.76 31.39h0.04c0.03 1.67-2.37 5.78-3.62 6.45-0.36 0.15-0.78 0.32-1.25 0.52-1.91 0.8-7.6 3.18-9.39 3.34-0.77-0.45-2.36-1.98-4.05-3.86 5.03-2.38 14.65-6.45 18.27-6.45m0-3c-6.12 0-22.98 8.27-22.97 8.55 0 0 5.96 7.51 8.25 7.76 0.09 0.01 0.18 0.01 0.28 0.01 2.54 0 9.26-2.97 12.01-4.09 2.85-1.17 8.22-10.44 3.72-12.05-0.34-0.12-0.78-0.18-1.29-0.18z' fill='%235D4037'/%3E%3Cpolyline points='30.29 103.37 31.17 108.44 37.99 106.57' fill='%238D6E63'/%3E%3Cpolyline points='47.01 107.96 50.67 111.08 55.27 108.39' fill='%23A1887F'/%3E%3Cpolyline points='70.45 105.84 76.92 107.91 78.15 102.63' fill='%23BCAAA4'/%3E%3Cpolyline points='84.19 96.2 90.9 95.4 90.06 90.03' fill='%238D6E63'/%3E%3ClinearGradient id='e' x1='90.754' x2='108.35' y1='79.097' y2='79.097' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%238D6E63' offset='.0037206'/%3E%3Cstop stop-color='%2376594F' offset='.4152'/%3E%3Cstop stop-color='%234E342E' offset='.9989'/%3E%3C/linearGradient%3E%3Cpath d='m97.03 83.58c-2.7 0-4.91-0.32-6.27-0.58l2.37-8.25c0.73-0.06 1.82-0.13 3.09-0.13 5.15 0 8.91 1.04 10.58 2.94 1.19 1.35 1.74 2.5 1.5 3.15-0.18 0.5-1.19 1.75-6.55 2.54-1.54 0.21-3.13 0.33-4.72 0.33z' fill='url(%23e)'/%3E%3Cpath d='m96.21 76.12c4.64 0 8.09 0.89 9.45 2.43 0.77 0.87 1.04 1.41 1.13 1.66-0.37 0.28-1.63 1.01-5.28 1.55-1.46 0.21-2.97 0.32-4.5 0.32-1.68 0-3.17-0.13-4.36-0.29l1.61-5.62c0.57-0.03 1.23-0.05 1.95-0.05m0-3c-2.45 0-4.25 0.23-4.25 0.23l-3.08 10.76s3.35 0.97 8.15 0.97c1.52 0 3.19-0.1 4.93-0.35 7.27-1.07 10.13-3.43 5.95-8.16-2.54-2.89-7.9-3.45-11.7-3.45z' fill='%235D4037'/%3E%3ClinearGradient id='d' x1='64.17' x2='64.17' y1='27.642' y2='107.86' gradientTransform='matrix(.9998 -.0211 .0211 .9998 -1.3443 1.3702)' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%235D2813' offset='.1715'/%3E%3Cstop stop-color='%236A3A27' offset='.2429'/%3E%3Cstop stop-color='%238D6859' offset='.3885'/%3E%3Cstop stop-color='%23C5B2AA' offset='.5932'/%3E%3Cstop stop-color='%23fff' offset='.7926'/%3E%3C/linearGradient%3E%3Cpath d='m52.52 107.19c-37.81-0.61-44.98-29.22-46.31-41.49-0.61-5.6-0.56-10.55-0.53-13.82 0.02-1.77 0.03-3.01-0.05-3.85 0.32-0.14 0.89-0.29 1.25-0.38 1.27-0.33 3.01-0.78 3.15-2.46 0.13-1.54-1.28-2.47-2.42-3.21-0.15-0.1-0.34-0.22-0.52-0.35 3.71-3.46 20.01-14.52 46.65-14.52h0.63c18.29 0.12 32.11 8.38 41.07 24.55 0.37 0.67 0.62 1.12 0.84 1.43 1.78 2.55 4.66 2.82 5.82 2.82 0.39 0 0.63-0.03 0.63-0.03 0.15-0.02 0.3-0.06 0.44-0.12l13.32-5.84c0.58-0.13 1.11-0.19 1.59-0.19 1.18 0 3.94 0 4.24 7.24 0.36 8.46-2.77 8.7-3.95 8.79-0.06 0-0.13 0.01-0.2 0.01-1.42 0-4.41-0.79-7.31-1.55-3.76-0.99-7.65-2.01-10.28-2.01-0.83 0-1.51 0.1-2.07 0.31-3.31 1.21-4.05 4.22-3.98 5.71-0.04 2.2-1.38 38.98-41 38.98-0.31-0.01-0.66-0.01-1.01-0.02z' fill='url(%23d)'/%3E%3Cpath d='m53.76 28.63h0.62c11.37 0.07 21.04 3.4 28.75 9.9 6.22 5.24 9.45 11.07 11 13.86 0.4 0.72 0.66 1.19 0.92 1.56 2.19 3.13 5.67 3.47 7.07 3.47 0.41 0 0.7-0.03 0.8-0.04 0.3-0.03 0.6-0.11 0.88-0.24l13.18-5.78c0.41-0.08 0.79-0.12 1.12-0.12 0.8 0 2.48 0 2.72 5.78 0.3 6.99-1.77 7.15-2.54 7.21h-0.08c-1.22 0-4.25-0.8-6.92-1.5-3.85-1.01-7.84-2.06-10.67-2.06-1.01 0-1.86 0.13-2.6 0.4-4.09 1.5-5.04 5.22-4.98 7.14-0.03 0.91-0.45 10.06-5.25 18.99-6.59 12.25-18.1 18.46-34.22 18.46-0.34 0-0.68 0-1.02-0.01-36.59-0.57-43.53-28.24-44.82-40.11-0.6-5.51-0.55-10.41-0.51-13.64 0.01-1.1 0.02-2.01 0.01-2.76 0.02 0 0.04-0.01 0.06-0.01 1.32-0.34 4.05-1.05 4.29-3.81 0.15-1.73-0.85-2.92-1.88-3.75 5.05-3.85 19.63-12.94 44.07-12.94m0-3.05c-31.09 0-47.47 14.49-48.44 15.71-0.97 1.23 3.32 2.41 3.2 3.77s-4.74 0.92-4.43 2.87-0.36 9.06 0.61 17.94c0.63 5.76 4.74 42.15 47.8 42.84 0.36 0.01 0.72 0.01 1.07 0.01 42 0 42.52-40.53 42.52-40.53s-0.21-3.09 2.98-4.25c0.41-0.15 0.93-0.21 1.55-0.21 4.55 0 14.12 3.56 17.59 3.56 0.11 0 0.22 0 0.32-0.01 4.13-0.32 5.62-4.05 5.35-10.37-0.23-5.45-1.87-8.7-5.77-8.7-0.63 0-1.32 0.08-2.06 0.26l-13.46 5.9s-0.17 0.02-0.46 0.02c-0.96 0-3.22-0.22-4.57-2.17-1.76-2.52-11.65-26.43-43.15-26.63-0.23-0.01-0.44-0.01-0.65-0.01z' fill='%236D4C41'/%3E%3ClinearGradient id='c' x1='37.747' x2='63.178' y1='49.106' y2='49.106' gradientTransform='matrix(.9998 -.0211 .0211 .9998 -1.3443 1.3702)' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%235D4037' offset='.0022355'/%3E%3Cstop stop-color='%23462D28' offset='.7745'/%3E%3Cstop stop-color='%233E2723' offset='.9989'/%3E%3C/linearGradient%3E%3Cpath d='m37.31 43.68s4.13 2.45 1.83 7.32 5.92 8.24 12.4 8.35 11.54-10.92 11.2-15.99c-0.35-5.06-15.24-5.74-25.43 0.32z' fill='url(%23c)'/%3E%3Cpolyline points='26.79 89.88 28.89 95.75 34.49 93.08' fill='%23BCAAA4'/%3E%3Cpolyline points='42.28 96.62 45.56 101.61 50.22 97.71' fill='%23BCAAA4'/%3E%3Cpolyline points='16.25 86.69 15.43 96.38 24.03 95.47' fill='%23D7CCC8'/%3E%3Cpolyline points='62.26 97.53 66.89 101.26 70.23 95.98' fill='%23BCAAA4'/%3E%3Cpolyline points='55.12 104.31 59.74 108.04 63.09 102.76' fill='%23BCAAA4'/%3E%3Cpolyline points='76.49 94.53 82.87 96.17 82.74 89.65' fill='%23D7CCC8'/%3E%3Cpolyline points='37.77 79.99 40.25 85.68 44.45 81.59' fill='%236D4C41'/%3E%3Cpolyline points='52.45 87.68 56.87 91.85 59.18 86.33' fill='%236D4C41'/%3E%3Cpolyline points='53.86 70.2 57.51 75.45 60.27 69.66' fill='%238D6E63'/%3E%3Cpolyline points='67.45 67.52 72.89 70.58 73 64.1' fill='%238D6E63'/%3E%3Cpolyline points='81.12 71.93 86.55 74.98 86.67 68.51' fill='%238D6E63'/%3E%3Cpolyline points='71.83 82.9 77.01 86.42 77.63 79.98' fill='%235D4037'/%3E%3Cpolyline points='86.87 58.21 88.2 50.26 80.04 51.38' fill='%233E2723'/%3E%3Cpolyline points='77.45 45.42 76.45 37.42 68.98 41.08' fill='%233E2723'/%3E%3Cpolyline points='83.66 38.32 82.49 28.88 73.68 33.21' fill='%234E342E'/%3E%3Cpolyline points='77.15 31.71 74.62 22.57 66.54 28.27' fill='%233E2723'/%3E%3Cpolyline points='44.38 29.09 36.37 22.65 32.34 32.32' fill='%234E342E' stroke='%233E2723' stroke-miterlimit='10' stroke-width='.8152'/%3E%3Cpolyline points='63.01 34.13 58.71 22.46 50.9 32.1' fill='%233E2723'/%3E%3Cpolyline points='55.09 28.11 49 19.79 42.82 27.93' fill='%233E2723'/%3E%3Cpolyline points='30.01 30.61 21.44 25.28 18.55 35.26' fill='%233E2723'/%3E%3Cpolyline points='71.23 30.98 67.42 21.27 59.44 27.41' fill='%234E342E'/%3E%3Cpolyline points='20.57 72.15 21.14 77.91 25.96 74.98' fill='%236D4C41'/%3E%3Cpolyline points='12.55 75.13 7 82.08 14.42 82.08' fill='%23BCAAA4'/%3E%3Cpolyline points='16.24 56.96 12.28 62.42 18.7 64.05' fill='%236D4C41'/%3E%3Cpolyline points='34.25 66.48 35.09 73.04 40.15 69.3' fill='%238D6E63'/%3E%3Cpath d='m33.66 39.32c-0.14 5.06-4.13 9.04-8.91 8.89s-8.54-4.37-8.4-9.43 4.13-9.04 8.91-8.89 8.54 4.37 8.4 9.43z' fill='%23fff'/%3E%3Cpath d='m28.16 42.6c-1.85 1.85-4.76 1.76-6.51-0.2-1.74-1.96-1.66-5.04 0.19-6.88s4.76-1.76 6.51 0.2c1.74 1.95 1.66 5.03-0.19 6.88z'/%3E%3Cg display='none'%3E%3Cg display='inline'%3E%3Cg opacity='.6'%3E%3Ccircle cx='-117.33' cy='64' r='28' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.2625'/%3E%3Cline x1='-97.33' x2='-97.33' y2='128' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x1='-137.33' x2='-137.33' y2='128' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x1='-117.33' x2='-117.33' y2='128' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x1='-53.33' x2='-181.33' y1='64' y2='64' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x1='-53.33' x2='-181.33' y1='44' y2='44' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x1='-53.33' x2='-181.33' y1='83.75' y2='83.75' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x1='-53.33' x2='-181.33' y1='128' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x1='-181.33' x2='-53.33' y1='128' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cg opacity='.61'%3E%3Cpath d='m-117.33 4.26c32.94 0 59.74 26.8 59.74 59.74s-26.8 59.74-59.74 59.74-59.74-26.8-59.74-59.74 26.79-59.74 59.74-59.74m0-0.26c-33.14 0-60 26.86-60 60s26.86 60 60 60 60-26.86 60-60-26.87-60-60-60z'/%3E%3C/g%3E%3Cpath d='m-73.36 115.97h-87.94c-4.42 0-8.03-3.61-8.03-8.03v-87.91c0-4.42 3.61-8.03 8.03-8.03h87.94c4.42 0 8.03 3.61 8.03 8.03v87.91c0 4.42-3.62 8.03-8.03 8.03z' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.2578'/%3E%3Cpath d='m-81.33 124h-72c-4.4 0-8-3.6-8-8v-104c0-4.4 3.6-8 8-8h72c4.4 0 8 3.6 8 8v104c0 4.4-3.6 8-8 8z' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.2628'/%3E%3Cpath d='m-67.57 108h-99.54c-5.63 0-10.23-4.6-10.23-10.23v-67.49c0-5.63 4.6-10.23 10.23-10.23h99.54c5.63 0 10.23 4.6 10.23 10.23v67.48c0.01 5.64-4.6 10.24-10.23 10.24z' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.2627'/%3E%3C/g%3E%3Cg opacity='.2'%3E%3Cdefs%3E%3Crect id='h' x='-181.33' width='128' height='128' opacity='.2'/%3E%3C/defs%3E%3CclipPath id='b'%3E%3Cuse xlink:href='%23h'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23b)'%3E%3Cg fill='none' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'%3E%3Cline x1='-209.33' x2='-209.33' y1='160' y2='-32'/%3E%3Cline x1='-205.33' x2='-205.33' y1='160' y2='-32'/%3E%3Cline x1='-201.33' x2='-201.33' y1='160' y2='-32'/%3E%3Cline x1='-197.33' x2='-197.33' y1='160' y2='-32'/%3E%3Cline x1='-193.33' x2='-193.33' y1='160' y2='-32'/%3E%3Cline x1='-189.33' x2='-189.33' y1='160' y2='-32'/%3E%3Cline x1='-185.33' x2='-185.33' y1='160' y2='-32'/%3E%3Cline x1='-181.33' x2='-181.33' y1='160' y2='-32'/%3E%3Cline x1='-177.33' x2='-177.33' y1='160' y2='-32'/%3E%3Cline x1='-173.33' x2='-173.33' y1='160' y2='-32'/%3E%3Cline x1='-169.33' x2='-169.33' y1='160' y2='-32'/%3E%3Cline x1='-165.33' x2='-165.33' y1='160' y2='-32'/%3E%3Cline x1='-161.33' x2='-161.33' y1='160' y2='-32'/%3E%3Cline x1='-157.33' x2='-157.33' y1='160' y2='-32'/%3E%3Cline x1='-153.33' x2='-153.33' y1='160' y2='-32'/%3E%3Cline x1='-149.33' x2='-149.33' y1='160' y2='-32'/%3E%3Cline x1='-145.33' x2='-145.33' y1='160' y2='-32'/%3E%3Cline x1='-141.33' x2='-141.33' y1='160' y2='-32'/%3E%3Cline x1='-137.33' x2='-137.33' y1='160' y2='-32'/%3E%3Cline x1='-133.33' x2='-133.33' y1='160' y2='-32'/%3E%3Cline x1='-129.33' x2='-129.33' y1='160' y2='-32'/%3E%3Cline x1='-125.33' x2='-125.33' y1='160' y2='-32'/%3E%3Cline x1='-121.33' x2='-121.33' y1='160' y2='-32'/%3E%3Cline x1='-117.33' x2='-117.33' y1='160' y2='-32'/%3E%3Cline x1='-113.33' x2='-113.33' y1='160' y2='-32'/%3E%3Cline x1='-109.33' x2='-109.33' y1='160' y2='-32'/%3E%3Cline x1='-105.33' x2='-105.33' y1='160' y2='-32'/%3E%3Cline x1='-101.33' x2='-101.33' y1='160' y2='-32'/%3E%3Cline x1='-97.33' x2='-97.33' y1='160' y2='-32'/%3E%3Cline x1='-93.33' x2='-93.33' y1='160' y2='-32'/%3E%3Cline x1='-89.33' x2='-89.33' y1='160' y2='-32'/%3E%3Cline x1='-85.33' x2='-85.33' y1='160' y2='-32'/%3E%3Cline x1='-81.33' x2='-81.33' y1='160' y2='-32'/%3E%3Cline x1='-77.33' x2='-77.33' y1='160' y2='-32'/%3E%3Cline x1='-73.33' x2='-73.33' y1='160' y2='-32'/%3E%3Cline x1='-69.33' x2='-69.33' y1='160' y2='-32'/%3E%3Cline x1='-65.33' x2='-65.33' y1='160' y2='-32'/%3E%3Cline x1='-61.33' x2='-61.33' y1='160' y2='-32'/%3E%3Cline x1='-57.33' x2='-57.33' y1='160' y2='-32'/%3E%3Cline x1='-53.33' x2='-53.33' y1='160' y2='-32'/%3E%3Cline x1='-49.33' x2='-49.33' y1='160' y2='-32'/%3E%3Cline x1='-45.33' x2='-45.33' y1='160' y2='-32'/%3E%3Cline x1='-44.33' x2='-44.33' y1='166.05' y2='-25.95'/%3E%3Cline x1='-37.33' x2='-37.33' y1='160' y2='-32'/%3E%3Cline x1='-33.33' x2='-33.33' y1='160' y2='-32'/%3E%3Cline x1='-29.33' x2='-29.33' y1='160' y2='-32'/%3E%3Cline x1='-25.33' x2='-25.33' y1='160' y2='-32'/%3E%3C/g%3E%3Cg fill='none' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'%3E%3Cline x1='-213.33' x2='-21.33' y1='-28' y2='-28'/%3E%3Cline x1='-213.33' x2='-21.33' y1='-24' y2='-24'/%3E%3Cline x1='-213.33' x2='-21.33' y1='-20' y2='-20'/%3E%3Cline x1='-213.33' x2='-21.33' y1='-16' y2='-16'/%3E%3Cline x1='-213.33' x2='-21.33' y1='-12' y2='-12'/%3E%3Cline x1='-213.33' x2='-21.33' y1='-8' y2='-8'/%3E%3Cline x1='-213.33' x2='-21.33' y1='-4' y2='-4'/%3E%3Cline x1='-213.33' x2='-21.33'/%3E%3Cline x1='-213.33' x2='-21.33' y1='4' y2='4'/%3E%3Cline x1='-213.33' x2='-21.33' y1='8' y2='8'/%3E%3Cline x1='-213.33' x2='-21.33' y1='12' y2='12'/%3E%3Cline x1='-213.33' x2='-21.33' y1='16' y2='16'/%3E%3Cline x1='-213.33' x2='-21.33' y1='20' y2='20'/%3E%3Cline x1='-213.33' x2='-21.33' y1='24' y2='24'/%3E%3Cline x1='-213.33' x2='-21.33' y1='28' y2='28'/%3E%3Cline x1='-213.33' x2='-21.33' y1='32' y2='32'/%3E%3Cline x1='-213.33' x2='-21.33' y1='36' y2='36'/%3E%3Cline x1='-213.33' x2='-21.33' y1='40' y2='40'/%3E%3Cline x1='-213.33' x2='-21.33' y1='44' y2='44'/%3E%3Cline x1='-213.33' x2='-21.33' y1='48' y2='48'/%3E%3Cline x1='-213.33' x2='-21.33' y1='52' y2='52'/%3E%3Cline x1='-213.33' x2='-21.33' y1='56' y2='56'/%3E%3Cline x1='-213.33' x2='-21.33' y1='60' y2='60'/%3E%3Cline x1='-213.33' x2='-21.33' y1='64' y2='64'/%3E%3Cline x1='-213.33' x2='-21.33' y1='68' y2='68'/%3E%3Cline x1='-213.33' x2='-21.33' y1='72' y2='72'/%3E%3Cline x1='-213.33' x2='-21.33' y1='76' y2='76'/%3E%3Cline x1='-213.33' x2='-21.33' y1='80' y2='80'/%3E%3Cline x1='-213.33' x2='-21.33' y1='84' y2='84'/%3E%3Cline x1='-213.33' x2='-21.33' y1='88' y2='88'/%3E%3Cline x1='-213.33' x2='-21.33' y1='92' y2='92'/%3E%3Cline x1='-213.33' x2='-21.33' y1='96' y2='96'/%3E%3Cline x1='-213.33' x2='-21.33' y1='100' y2='100'/%3E%3Cline x1='-213.33' x2='-21.33' y1='104' y2='104'/%3E%3Cline x1='-213.33' x2='-21.33' y1='108' y2='108'/%3E%3Cline x1='-213.33' x2='-21.33' y1='112' y2='112'/%3E%3Cline x1='-213.33' x2='-21.33' y1='116' y2='116'/%3E%3Cline x1='-213.33' x2='-21.33' y1='120' y2='120'/%3E%3Cline x1='-213.33' x2='-21.33' y1='124' y2='124'/%3E%3Cline x1='-213.33' x2='-21.33' y1='128' y2='128'/%3E%3Cline x1='-213.33' x2='-21.33' y1='132' y2='132'/%3E%3Cline x1='-213.33' x2='-21.33' y1='136' y2='136'/%3E%3Cline x1='-213.33' x2='-21.33' y1='140' y2='140'/%3E%3Cline x1='-213.33' x2='-21.33' y1='144' y2='144'/%3E%3Cline x1='-213.33' x2='-21.33' y1='148' y2='148'/%3E%3Cline x1='-213.33' x2='-21.33' y1='152' y2='152'/%3E%3Cline x1='-213.33' x2='-21.33' y1='156' y2='156'/%3E%3C/g%3E%3Cpath d='m-21.58-31.75v191.5h-191.5v-191.5h191.5m0.25-0.25h-192v192h192v-192z'/%3E%3C/g%3E%3C/g%3E%3Cg fill='%23F44336'%3E%3Crect x='-181.33' width='4' height='128' opacity='.3'/%3E%3Crect x='-57.33' width='4' height='128' opacity='.3'/%3E%3Crect transform='matrix(-1.837e-16 1 -1 -1.837e-16 -115.33 119.33)' x='-119.33' y='-58' width='4' height='120' opacity='.3'/%3E%3Crect transform='matrix(-1.837e-16 1 -1 -1.837e-16 8.6667 243.33)' x='-119.33' y='66' width='4' height='120' opacity='.3'/%3E%3C/g%3E%3C/g%3E%3Cg display='inline'%3E%3Cg opacity='.6'%3E%3Ccircle cx='64' cy='64' r='28' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.2625'/%3E%3Cline x1='84' x2='84' y2='128' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x1='44' x2='44' y2='128' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x1='64' x2='64' y2='128' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x1='128' y1='64' y2='64' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x1='128' y1='44' y2='44' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x1='128' y1='83.75' y2='83.75' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x1='128' y1='128' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cline x2='128' y1='128' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'/%3E%3Cg opacity='.61'%3E%3Cpath d='M64,4.26c32.94,0,59.74,26.8,59.74,59.74S96.94,123.74,64,123.74S4.26,96.94,4.26,64S31.06,4.26,64,4.26 M64,4 C30.86,4,4,30.86,4,64s26.86,60,60,60s60-26.86,60-60S97.14,4,64,4L64,4z'/%3E%3C/g%3E%3Cpath d='m107.97 115.97h-87.94c-4.42 0-8.03-3.61-8.03-8.03v-87.91c0-4.42 3.61-8.03 8.03-8.03h87.94c4.42 0 8.03 3.61 8.03 8.03v87.91c0 4.42-3.61 8.03-8.03 8.03z' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.2578'/%3E%3Cpath d='m100 124h-72c-4.4 0-8-3.6-8-8v-104c0-4.4 3.6-8 8-8h72c4.4 0 8 3.6 8 8v104c0 4.4-3.6 8-8 8z' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.2628'/%3E%3Cpath d='M113.77,108H14.23 C8.6,108,4,103.4,4,97.77V30.28c0-5.63,4.6-10.23,10.23-10.23h99.54c5.63,0,10.23,4.6,10.23,10.23v67.48 C124,103.4,119.4,108,113.77,108z' fill='none' opacity='.61' stroke='%23000' stroke-miterlimit='10' stroke-width='.2627'/%3E%3C/g%3E%3Cg opacity='.2'%3E%3Cdefs%3E%3Crect id='g' width='128' height='128' opacity='.2'/%3E%3C/defs%3E%3CclipPath id='a'%3E%3Cuse xlink:href='%23g'/%3E%3C/clipPath%3E%3Cg clip-path='url(%23a)'%3E%3Cg fill='none' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'%3E%3Cline x1='-28' x2='-28' y1='160' y2='-32'/%3E%3Cline x1='-24' x2='-24' y1='160' y2='-32'/%3E%3Cline x1='-20' x2='-20' y1='160' y2='-32'/%3E%3Cline x1='-16' x2='-16' y1='160' y2='-32'/%3E%3Cline x1='-12' x2='-12' y1='160' y2='-32'/%3E%3Cline x1='-8' x2='-8' y1='160' y2='-32'/%3E%3Cline x1='-4' x2='-4' y1='160' y2='-32'/%3E%3Cline y1='160' y2='-32'/%3E%3Cline x1='4' x2='4' y1='160' y2='-32'/%3E%3Cline x1='8' x2='8' y1='160' y2='-32'/%3E%3Cline x1='12' x2='12' y1='160' y2='-32'/%3E%3Cline x1='16' x2='16' y1='160' y2='-32'/%3E%3Cline x1='20' x2='20' y1='160' y2='-32'/%3E%3Cline x1='24' x2='24' y1='160' y2='-32'/%3E%3Cline x1='28' x2='28' y1='160' y2='-32'/%3E%3Cline x1='32' x2='32' y1='160' y2='-32'/%3E%3Cline x1='36' x2='36' y1='160' y2='-32'/%3E%3Cline x1='40' x2='40' y1='160' y2='-32'/%3E%3Cline x1='44' x2='44' y1='160' y2='-32'/%3E%3Cline x1='48' x2='48' y1='160' y2='-32'/%3E%3Cline x1='52' x2='52' y1='160' y2='-32'/%3E%3Cline x1='56' x2='56' y1='160' y2='-32'/%3E%3Cline x1='60' x2='60' y1='160' y2='-32'/%3E%3Cline x1='64' x2='64' y1='160' y2='-32'/%3E%3Cline x1='68' x2='68' y1='160' y2='-32'/%3E%3Cline x1='72' x2='72' y1='160' y2='-32'/%3E%3Cline x1='76' x2='76' y1='160' y2='-32'/%3E%3Cline x1='80' x2='80' y1='160' y2='-32'/%3E%3Cline x1='84' x2='84' y1='160' y2='-32'/%3E%3Cline x1='88' x2='88' y1='160' y2='-32'/%3E%3Cline x1='92' x2='92' y1='160' y2='-32'/%3E%3Cline x1='96' x2='96' y1='160' y2='-32'/%3E%3Cline x1='100' x2='100' y1='160' y2='-32'/%3E%3Cline x1='104' x2='104' y1='160' y2='-32'/%3E%3Cline x1='108' x2='108' y1='160' y2='-32'/%3E%3Cline x1='112' x2='112' y1='160' y2='-32'/%3E%3Cline x1='116' x2='116' y1='160' y2='-32'/%3E%3Cline x1='120' x2='120' y1='160' y2='-32'/%3E%3Cline x1='124' x2='124' y1='160' y2='-32'/%3E%3Cline x1='128' x2='128' y1='160' y2='-32'/%3E%3Cline x1='132' x2='132' y1='160' y2='-32'/%3E%3Cline x1='136' x2='136' y1='160' y2='-32'/%3E%3Cline x1='137' x2='137' y1='166.05' y2='-25.95'/%3E%3Cline x1='144' x2='144' y1='160' y2='-32'/%3E%3Cline x1='148' x2='148' y1='160' y2='-32'/%3E%3Cline x1='152' x2='152' y1='160' y2='-32'/%3E%3Cline x1='156' x2='156' y1='160' y2='-32'/%3E%3C/g%3E%3Cg fill='none' stroke='%23000' stroke-miterlimit='10' stroke-width='.25'%3E%3Cline x1='-32' x2='160' y1='-28' y2='-28'/%3E%3Cline x1='-32' x2='160' y1='-24' y2='-24'/%3E%3Cline x1='-32' x2='160' y1='-20' y2='-20'/%3E%3Cline x1='-32' x2='160' y1='-16' y2='-16'/%3E%3Cline x1='-32' x2='160' y1='-12' y2='-12'/%3E%3Cline x1='-32' x2='160' y1='-8' y2='-8'/%3E%3Cline x1='-32' x2='160' y1='-4' y2='-4'/%3E%3Cline x1='-32' x2='160'/%3E%3Cline x1='-32' x2='160' y1='4' y2='4'/%3E%3Cline x1='-32' x2='160' y1='8' y2='8'/%3E%3Cline x1='-32' x2='160' y1='12' y2='12'/%3E%3Cline x1='-32' x2='160' y1='16' y2='16'/%3E%3Cline x1='-32' x2='160' y1='20' y2='20'/%3E%3Cline x1='-32' x2='160' y1='24' y2='24'/%3E%3Cline x1='-32' x2='160' y1='28' y2='28'/%3E%3Cline x1='-32' x2='160' y1='32' y2='32'/%3E%3Cline x1='-32' x2='160' y1='36' y2='36'/%3E%3Cline x1='-32' x2='160' y1='40' y2='40'/%3E%3Cline x1='-32' x2='160' y1='44' y2='44'/%3E%3Cline x1='-32' x2='160' y1='48' y2='48'/%3E%3Cline x1='-32' x2='160' y1='52' y2='52'/%3E%3Cline x1='-32' x2='160' y1='56' y2='56'/%3E%3Cline x1='-32' x2='160' y1='60' y2='60'/%3E%3Cline x1='-32' x2='160' y1='64' y2='64'/%3E%3Cline x1='-32' x2='160' y1='68' y2='68'/%3E%3Cline x1='-32' x2='160' y1='72' y2='72'/%3E%3Cline x1='-32' x2='160' y1='76' y2='76'/%3E%3Cline x1='-32' x2='160' y1='80' y2='80'/%3E%3Cline x1='-32' x2='160' y1='84' y2='84'/%3E%3Cline x1='-32' x2='160' y1='88' y2='88'/%3E%3Cline x1='-32' x2='160' y1='92' y2='92'/%3E%3Cline x1='-32' x2='160' y1='96' y2='96'/%3E%3Cline x1='-32' x2='160' y1='100' y2='100'/%3E%3Cline x1='-32' x2='160' y1='104' y2='104'/%3E%3Cline x1='-32' x2='160' y1='108' y2='108'/%3E%3Cline x1='-32' x2='160' y1='112' y2='112'/%3E%3Cline x1='-32' x2='160' y1='116' y2='116'/%3E%3Cline x1='-32' x2='160' y1='120' y2='120'/%3E%3Cline x1='-32' x2='160' y1='124' y2='124'/%3E%3Cline x1='-32' x2='160' y1='128' y2='128'/%3E%3Cline x1='-32' x2='160' y1='132' y2='132'/%3E%3Cline x1='-32' x2='160' y1='136' y2='136'/%3E%3Cline x1='-32' x2='160' y1='140' y2='140'/%3E%3Cline x1='-32' x2='160' y1='144' y2='144'/%3E%3Cline x1='-32' x2='160' y1='148' y2='148'/%3E%3Cline x1='-32' x2='160' y1='152' y2='152'/%3E%3Cline x1='-32' x2='160' y1='156' y2='156'/%3E%3C/g%3E%3Cpath d='m159.75-31.75v191.5h-191.5v-191.5h191.5m0.25-0.25h-192v192h192v-192z'/%3E%3C/g%3E%3C/g%3E%3Cg fill='%23F44336'%3E%3Crect width='4' height='128' opacity='.3'/%3E%3Crect x='124' width='4' height='128' opacity='.3'/%3E%3Crect transform='matrix(-1.837e-16 1 -1 -1.837e-16 66 -62)' x='62' y='-58' width='4' height='120' opacity='.3'/%3E%3Crect transform='matrix(-1.837e-16 1 -1 -1.837e-16 190 62)' x='62' y='66' width='4' height='120' opacity='.3'/%3E%3C/g%3E%3C/g%3E%3C/g%3E%3C/svg%3E" textColor="#fff" badge=""></favicon-badge>

    {# Script loader for sourced scripts, as they cannot be authorized by a CSP hash. #}
    {% include 'partials/script-loader.njk' %}
    {% set apiScripts %}
      loadScript('https://unpkg.com/own-window@1.0.3/dist/index.min.js', null);
    {% endset %}
    <script>{{ apiScripts | minifyJs | cspHash | safe }}</script>

    {% set script %}
      if ('serviceWorker' in navigator) {
        window.addEventListener('load', async () => {
          try {
            const registration = await navigator.serviceWorker.register('sw.js');
            console.log(
              'Service worker registered for scope',
              registration.scope,
            );
          } catch (err) {
            console.error(err.name, err.message);
          }
        });
      }
    {% endset %}
    <script>{{ script | minifyJs | cspHash | safe }}</script>

    {% set apiScripts %}
      loadScript('https://unpkg.com/favicon-badge@2.0.0/dist/FavIconBadge.js', null);
    {% endset %}
    <script>{{ apiScripts | minifyJs | cspHash | safe }}</script>

    {% set script %}
      const favicon = document.querySelector('favicon-badge');
      const installButton = document.querySelector('#install');
      const supportsAppBadge = 'setAppBadge' in navigator;
      let setAppBadge;
      let i = 0;
      const getAppBadgeValue = () => {
        if (i > 9) {
          i = 0;
        }
        return i++;
      };
      const setAppBadgeFavicon = (value) => {
        favicon.badge = value;
      };
      const setAppBadgeNative = (value) => {
        navigator.setAppBadge(value);
      }
      if (
        matchMedia('(display-mode: standalone)').matches &&
        supportsAppBadge
      ) {
        setAppBadge = setAppBadgeNative;
      } else {
        setAppBadge = setAppBadgeFavicon;
      }
      setInterval(() => {
        setAppBadge(getAppBadgeValue());
      }, 1000);
      if ('BeforeInstallPromptEvent' in window) {
        let installEvent = null;
        const onInstall = () => {
          installButton.disabled = true;
          installEvent = null;
          if (supportsAppBadge) {
            favicon.badge = false;
            setAppBadge = setAppBadgeNative;
          }
        };
        window.addEventListener('beforeinstallprompt', (event) => {
          event.preventDefault();
          installEvent = event;
          installButton.disabled = false;
        });
        installButton.addEventListener('click', async () => {
          if (!installEvent) {
            return;
          }
          installEvent.prompt();
          const result = await installEvent.userChoice;
          if (result.outcome === 'accepted') {
            onInstall();
          }
        });
        window.addEventListener('appinstalled', (event) => {
          onInstall();
        });
      }
    {% endset %}
    <script>{{ script | minifyJs | cspHash | safe }}</script>
  </body>
</html>
